package org.recursed.simpleweather.forecast;

import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.recursed.simpleweather.WeatherGallery;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Responsible for parsing through the XML recovered from an NWS
 * hit. There are two core sections to look for:
 * <ul>
 * 	<li>time-layout: which contains sections/spans of time</li>
 *  <li>parameters: which contains specific blocks of weather data</li>
 * </ul>
 * 
 * @author keerat
 *
 */
public class NWSWeatherXMLParser extends DefaultHandler {
	
    //<creation-date refresh-frequency="PT1H">2009-03-14T20:58:51Z</creation-date>
	private static final String CREATION_DATE = "creation-date";
	private static final SimpleDateFormat CREATED_DATE_FORMATTER = 
		new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
	// <start-valid-time>2009-03-14T08:00:00-04:00</start-valid-time>
	private static final SimpleDateFormat TIME_LAYOUT_DATE_FORMATTER = 
		new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
	
	// <moreWeatherInformation applicable-location="point1">
	//  http://forecast.weather.gov/MapClick.php?textField1=38.99&textField2=-77.01
	// </moreWeatherInformation>	
	private static final String MORE_INFO = "moreWeatherInformation";
	
	private static final String LAYOUT_KEY = "layout-key";
	private static final String START_VALID_TIME = "start-valid-time";
	private static final String END_VALID_TIME = "end-valid-time";
	
	// condition icons
	private static final String CONDITIONS = "conditions-icon";
	private static final String TIME_LAYOUT = "time-layout";
	private static final String ICON_LINK = "icon-link";
	
	private InputStream in;
	private String currentTag;
	private NWSWeatherObject nwo;
	private WeatherGallery parent;
		
	public NWSWeatherXMLParser(InputStream in) {
		this.in = in;
		this.currentTag = "";
		nwo = new NWSWeatherObject();
	}
	
	public void parse(WeatherGallery parent) throws Exception {
		SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
		SAXParser parser = saxParserFactory.newSAXParser();
		this.parent = parent;
		parser.parse(in, this);
	}

	private void handleCreationDate(String dateString) {
		try {
			Date date = CREATED_DATE_FORMATTER.parse(dateString);
			nwo.setCreatedOn(date);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
	
	
	private void handleStartValidTime(String startTimeString) {
		try {
			Date date = TIME_LAYOUT_DATE_FORMATTER.parse(startTimeString);
			nwo.addNewTimeBand(date);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
	
	private void handleEndValidTime(String endTimeString) {
		try {
			Date date = TIME_LAYOUT_DATE_FORMATTER.parse(endTimeString);
			nwo.closeCurrentTimeBand(date);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
 	
	@Override
	public void startElement(String uri, String localName, String name,
			Attributes attributes) throws SAXException {
		currentTag = localName;
		if (currentTag.equals(CONDITIONS)) {
			// rip the time layout
			String timeLayoutName = attributes.getValue(TIME_LAYOUT);
			nwo.setConditionIconTimeLayout(timeLayoutName);
		}
	}
	
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if (currentTag.equals(CREATION_DATE)) {
			handleCreationDate(new String(ch, start, length));
		}
		if (currentTag.equals(MORE_INFO)) {
			nwo.setMoreInfoLink(new String(ch, start, length));
		}
		if (currentTag.equals(LAYOUT_KEY)) {
			nwo.addTimeLayout(new String(ch, start, length));
		}
		if (currentTag.equals(START_VALID_TIME)) {
			handleStartValidTime(new String(ch, start, length));
		}
		if (currentTag.equals(END_VALID_TIME)) {
			handleEndValidTime(new String(ch, start, length));
		}
		if (currentTag.equals(ICON_LINK)) {
			nwo.addConditionIconLink(new String(ch, start, length));
		}
	}
	
	@Override
	public void endElement(String uri, String localName, String name)
			throws SAXException {
		currentTag = "";
	}

	@Override
	public void endDocument() throws SAXException {
		parent.gotWeather(nwo);
	}

	
	
}
